package router

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"strings"

	"gitee.com/liukexing/isrn/api/basic"
	apidata "gitee.com/liukexing/isrn/api/data"
	"gitee.com/liukexing/isrn/model"
)

type TranHandller func(data *model.Trans) error

const ()

var (
	TranAction TranHandller
)

func TranCheck(data *model.Trans, sender *ConnectInfo) error {
	//transid
	if data.TransId != sender.NodeId {
		return errors.New("transid Check Failed")
	}
	//Trans
	trans := data.PackInfo.Trans
	if len(trans) == 0 || trans[0] != nodeid {
		return errors.New("Trans Check Failed")
	}
	//Trans Sign
	transok, err := sender.RCyprto.Verify(data.Data, data.Sign)
	if err != nil {
		return err
	}
	if !transok {
		return errors.New("Trans Sign Check Failed")
	}

	return nil
}

func TranController(data *model.Trans, isEncrypt bool, sender *ConnectInfo) error {
	err := TranCheck(data, sender)
	if err != nil {
		return err
	}

	//Pack Tran
	if data.PackInfo.Receiver != nodeid {
		return TranTrans(data)
	}
	//Action
	//download data to Trans
	catc := basic.CatCommand{*sh}
	file, err := catc.Cat(string(data.Data))
	if err != nil {
		return err
	}
	trandata, err := ioutil.ReadAll(file)
	if err != nil {
		return err
	}
	data.Data = trandata
	return TranAction(data)
}

func TranTrans(data *model.Trans) error {
	//load  data info
	objectc := apidata.ObjectCommand{*sh}
	stat, err := objectc.Stat(string(data.Data))
	if err != nil {
		return err
	}
	fmt.Println(string(data.Data))
	fmt.Println(stat.DataSize)
	fmt.Println(data.PackInfo.Lengh)
	trans := data.PackInfo.Trans
	if len(trans) > 10 {
		return errors.New("Trans Nodes Too many")
	}
	conns := strings.Join(trans[1:], ",")
	data.PackInfo.Trans = strings.Split(conns, ",")
	data.TransId = nodeid
	nextTran := data.PackInfo.Trans[0]
	if conn, ok := connectlist[nextTran]; ok {
		sn, err := conn.RCyprto.Sign(data.Data)
		if err != nil {
			return err
		}
		data.Sign = sn
		msg, err := getTransByte(data, true, &conn.RCyprto)
		if err != nil {
			return err
		}
		conn.SendMsg(msg)
		return nil
	}
	l := listenlist.Front()
	for l != nil {
		v := l.Value.(*ConnectInfo)
		if v.Active && v.NodeId == nextTran {
			sn, err := v.RCyprto.Sign(data.Data)
			if err != nil {
				return err
			}
			data.Sign = sn
			msg, err := getTransByte(data, true, &v.RCyprto)
			if err != nil {
				return err
			}
			v.SendMsg(msg)
			return nil
		}
		l = l.Next()
	}
	return errors.New("Trans Nodes Not Find")
}

func TransSend(receiver string, router []string, info *model.TranInfo) error {
	data, err := info.GetByte()
	if err != nil {
		return err
	}
	//data upload
	add := &basic.AddCommand{*sh}
	hashid, err := add.AddNoPin(bytes.NewReader(data))
	if err != nil {
		return err
	}
	//trans file token
	trans := &model.Trans{}
	trans.CreatPackInfo([]byte(hashid), []byte(""), nodeid, receiver)
	trans.PackInfo.Trans = router
	trans.PackInfo.Lengh = len(data)
	trans.PackType = model.Tran

	return TranTrans(trans)
}
